//package com.geek.factory.service.impl;
//import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
//import com.baomidou.mybatisplus.core.metadata.IPage;
//import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
//import com.geek.factory.entity.RoleMenu;
//import com.geek.factory.mapper.RoleMapper;
//import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
//import com.geek.factory.entity.Role;
//import com.geek.factory.mapper.RoleMenuMapper;
//import com.geek.factory.service.RoleService;
//import org.springframework.beans.factory.annotation.Autowired;
//import org.springframework.stereotype.Service;
//import org.springframework.transaction.annotation.Transactional;
//
//import java.util.List;
//import java.util.stream.Collectors;
//
///**
// * <p>
// *  服务实现类
// * </p>
// *
// * @author author
// * @since 2025-06-24
// */
//@Service
//public class RoleServiceImpl extends ServiceImpl<RoleMapper, Role> implements RoleService {
//    @Override
//    public IPage<Role> pageQuery(Page<Role> page, String roleName, Integer status) {
//        QueryWrapper<Role> wrapper = new QueryWrapper<>();
//        if (roleName != null && !roleName.isEmpty()) {
//            wrapper.like("role_name", roleName);
//        }
//        if (status != null) {
//            wrapper.eq("status", status);
//        }
//        wrapper.orderByDesc("create_time");
//        return this.page(page, wrapper);
//    }
//
//
//    @Autowired
//    private RoleMenuMapper roleMenuMapper;
//    @Override
//    public List<Integer> getRoleMenuIds(Integer roleId) {
//        // 查询角色的菜单关联记录
//        QueryWrapper<RoleMenu> wrapper = new QueryWrapper<>();
//        wrapper.eq("role_id", roleId);
//        List<RoleMenu> roleMenus = roleMenuMapper.selectList(wrapper);
//
//        // 提取菜单ID列表
//        return roleMenus.stream()
//                .map(RoleMenu::getMenuId)
//                .collect(Collectors.toList());
//    }
//
//    @Override
//    @Transactional(rollbackFor = Exception.class)
//    public boolean setRoleMenus(Integer roleId, List<Integer> menuIds) {
//        try {
//            // 先删除原有的关联
//            QueryWrapper<RoleMenu> wrapper = new QueryWrapper<>();
//            wrapper.eq("role_id", roleId);
//            roleMenuMapper.delete(wrapper);
//
//            // 如果菜单ID列表为空，则只删除不新增
//            if (menuIds == null || menuIds.isEmpty()) {
//                return true;
//            }
//
//            // 再批量添加新的关联
//            for (Integer menuId : menuIds) {
//                RoleMenu roleMenu = new RoleMenu();
//                roleMenu.setRoleId(roleId);
//                roleMenu.setMenuId(menuId);
//                roleMenuMapper.insert(roleMenu);
//            }
//
//            return true;
//        } catch (Exception e) {
//            log.error("设置角色菜单权限失败：", e);
//            throw new RuntimeException("设置角色菜单权限失败", e);
//        }
//    }
//
//    @Override
//    @Transactional(rollbackFor = Exception.class)
//    public boolean removeRoleAndMenus(Integer roleId) {
//        try {
//            // 先删除角色菜单关联
//            QueryWrapper<RoleMenu> wrapper = new QueryWrapper<>();
//            wrapper.eq("role_id", roleId);
//            roleMenuMapper.delete(wrapper);
//
//            // 再删除角色
//            return this.removeById(roleId);
//        } catch (Exception e) {
//            log.error("删除角色及其菜单关联失败：", e);
//            throw new RuntimeException("删除角色及其菜单关联失败", e);
//        }
//    }
//}
package com.geek.factory.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.geek.factory.constant.RedisConstant;
import com.geek.factory.entity.RoleMenu;
import com.geek.factory.mapper.RoleMapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.geek.factory.entity.Role;
import com.geek.factory.mapper.RoleMenuMapper;
import com.geek.factory.service.RoleService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author author
 * @since 2025-06-24
 */
@Slf4j
@CacheConfig(cacheNames = "role")
@Service
public class RoleServiceImpl extends ServiceImpl<RoleMapper, Role> implements RoleService {
    @Override
    public IPage<Role> pageQuery(Page<Role> page, String roleName, Integer status) {
        QueryWrapper<Role> wrapper = new QueryWrapper<>();
        if (roleName != null && !roleName.isEmpty()) {
            wrapper.like("role_name", roleName);
        }
        if (status != null) {
            wrapper.eq("status", status);
        }
        wrapper.orderByDesc("create_time");
        return this.page(page, wrapper);
    }

    @Autowired
    private RedisTemplate<String, Object> redisTemplate;

    @Autowired
    private RoleMenuMapper roleMenuMapper;

    @Cacheable(key = "'" + RedisConstant.ROLE_MENU_KEY + "_' + #roleId")
    @Override
    public List<Integer> getRoleMenuIds(Integer roleId) {
        // 查询角色的菜单关联记录
        QueryWrapper<RoleMenu> wrapper = new QueryWrapper<>();
        wrapper.eq("role_id", roleId);
        List<RoleMenu> roleMenus = roleMenuMapper.selectList(wrapper);

        // 提取菜单ID列表
        return roleMenus.stream()
                .map(RoleMenu::getMenuId)
                .collect(Collectors.toList());
    }

    @CacheEvict(value = {RedisConstant.MENU_KEY, "role"}, allEntries = true)
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean setRoleMenus(Integer roleId, List<Integer> menuIds) {
        try {
            // 1. 先删除缓存
            redisTemplate.delete(RedisConstant.MENU_KEY + "::*");
            redisTemplate.delete("role::" + RedisConstant.ROLE_MENU_KEY + "_" + roleId);

            // 2. 先删除原有的关联
            QueryWrapper<RoleMenu> wrapper = new QueryWrapper<>();
            wrapper.eq("role_id", roleId);
            roleMenuMapper.delete(wrapper);

            // 3. 如果菜单ID列表为空，则只删除不新增
            if (menuIds == null || menuIds.isEmpty()) {
                // 4. 延迟双删策略，再次删除缓存
                try {
                    TimeUnit.MILLISECONDS.sleep(300);
                    redisTemplate.delete(RedisConstant.MENU_KEY + "::*");
                    redisTemplate.delete("role::" + RedisConstant.ROLE_MENU_KEY + "_" + roleId);
                } catch (InterruptedException e) {
                    log.error("延迟双删失败", e);
                    Thread.currentThread().interrupt();
                }
                return true;
            }

            // 5. 再批量添加新的关联
            for (Integer menuId : menuIds) {
                RoleMenu roleMenu = new RoleMenu();
                roleMenu.setRoleId(roleId);
                roleMenu.setMenuId(menuId);
                roleMenuMapper.insert(roleMenu);
            }

            // 6. 延迟双删策略，再次删除缓存
            try {
                TimeUnit.MILLISECONDS.sleep(300);
                redisTemplate.delete(RedisConstant.MENU_KEY + "::*");
                redisTemplate.delete("role::" + RedisConstant.ROLE_MENU_KEY + "_" + roleId);
            } catch (InterruptedException e) {
                log.error("延迟双删失败", e);
                Thread.currentThread().interrupt();
            }

            return true;
        } catch (Exception e) {
            log.error("设置角色菜单权限失败：", e);
            throw new RuntimeException("设置角色菜单权限失败", e);
        }
    }

    @CacheEvict(value = {RedisConstant.MENU_KEY, "role"}, allEntries = true)
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean removeRoleAndMenus(Integer roleId) {
        try {
            // 1. 先删除缓存
            redisTemplate.delete(RedisConstant.MENU_KEY + "::*");
            redisTemplate.delete("role::" + RedisConstant.ROLE_MENU_KEY + "_" + roleId);

            // 2. 先删除角色菜单关联
            QueryWrapper<RoleMenu> wrapper = new QueryWrapper<>();
            wrapper.eq("role_id", roleId);
            roleMenuMapper.delete(wrapper);

            // 3. 再删除角色
            boolean result = this.removeById(roleId);

            // 4. 延迟双删策略，再次删除缓存
            try {
                TimeUnit.MILLISECONDS.sleep(300);
                redisTemplate.delete(RedisConstant.MENU_KEY + "::*");
                redisTemplate.delete("role::" + RedisConstant.ROLE_MENU_KEY + "_" + roleId);
            } catch (InterruptedException e) {
                log.error("延迟双删失败", e);
                Thread.currentThread().interrupt();
            }

            return result;
        } catch (Exception e) {
            log.error("删除角色及其菜单关联失败：", e);
            throw new RuntimeException("删除角色及其菜单关联失败", e);
        }
    }
}
